package request

import (
	"fmt"
	"io"
	"net/http"
	"strings"
	"sync"
	"time"
)

var (
	POST    = "POST"
	GET     = "GET"
	PUT     = "PUT"
	DELETE  = "DELETE"
	OPTIONS = "OPTIONS"

	HTTP       = "HTTP"
	HTTPS      = "HTTPS"
	TCP        = "TCP"
	WEBSOCKET  = "WEBSOCKET"
	WEBSOCKETS = "WEBSOCKETS"

	ErrRequest = -1 // 请求失败
	ErrCheck   = -2 // 校验失败
)

var CH = make(chan *Response, 1000)
var ConcurrencyMap = &CMap{
	TN:    0,
	CN:    0,
	mutex: sync.RWMutex{},
}

type CMap struct {
	TN    int
	CN    int
	mutex sync.RWMutex
}

func (c *CMap) TNAdd(num int) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.TN += num
}
func (c *CMap) CNAdd(num int) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.CN += num
}

func (c *CMap) TNGet() int {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	return c.TN
}

func (c *CMap) CNGet() int {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	return c.CN
}

func (c *CMap) TNDel(num int) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.TN -= num
	if c.TN < 0 {
		c.TN = 0
	}
}

func (c *CMap) CNDel(num int) {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	c.CN -= num
	if c.CN < 0 {
		c.CN = 0
	}
}

type Request struct {
	URL       string            // 请求地址
	Scheme    string            // 请求类型 HTTP/ WEBSOCKET/ TCP
	Method    string            // 请求方法 GET/ POST/ PUT/ DELETE/ OPTIONS
	Headers   map[string]string // 请求头 Headers
	Body      string            // 请求体 body
	Cookies   []*http.Cookie
	Verify    func([]byte) bool // 验证的方法
	Timeout   time.Duration     // 请求超时时间
	Debug     bool              // 是否开启Debug模式
	MaxCon    int               // 每个连接的请求数
	SSL       bool              // 证书验证
	Keepalive bool              // 是否开启长连接
	Redirect  bool              // 是否重定向
	globMap   map[string]any
	GlobFun   func(http.Response) map[string]any // 全局变量
}

type Response struct {
	ChanID        int  // 消息ID
	Time          int  // 请求时间 纳秒
	IsSucceed     bool // 是否请求成功
	StatusCode    int
	ReceivedBytes int
	Cookies       []*http.Cookie
}

// Print 格式化打印
func (r *Request) Print() {
	if r == nil {
		return
	}
	result := fmt.Sprintf("request:\n\t scheme:%s \n\t url:%s \n\t method:%s \n\t headers:%v \n\t", r.Scheme, r.URL, r.Method,
		r.Headers)
	result = fmt.Sprintf(" %s data:%v \n\t", result, r.Body)
	result = fmt.Sprintf(" %s timeout:%s \n\t debug:%v \n\t", result, r.Timeout, r.Debug)
	result = fmt.Sprintf(" %s ssl：%v \n\t keepalive：%v \n\t maxCon:%v ", result, r.SSL, r.Keepalive, r.MaxCon)
	fmt.Println(result)
}

// SetBody 格式化请求体
func (r *Request) SetBody() (body io.Reader) {
	return strings.NewReader(r.Body)
}

// SetHeaders 设置请求头
func (r *Request) SetHeaders() map[string]string {
	var result = make(map[string]string, len(r.Headers))
	for k, v := range r.Headers {
		result[k] = v
	}
	return result
}
